import { TimeZone } from '@utils/time.zone';
import { i18nRender } from '@/locales';
const SysConf = {
  QQ: {
    code: '345746703',
    key: 'b1b2b4f0394c5a32c3e335bdc6eca505f5f3cee9e822e657a9978deb8440176e',
  },
  setCookie: function (c_name, value, expiredays) {
    var exdate = new Date();
    exdate = exdate.getTime() + expiredays;
    exdate = new Date(exdate);
    document.cookie =
      c_name +
      '=' +
      escape(value) +
      (expiredays == null ? '' : ';expires=' + exdate.toGMTString()) +
      ';path=/';
  },
  getCookie: function (c_name) {
    if (document.cookie.length > 0) {
      let c_start = document.cookie.indexOf(c_name + '=');
      if (c_start != -1) {
        c_start = c_start + c_name.length + 1;
        let c_end = document.cookie.indexOf(';', c_start);
        if (c_end == -1) c_end = document.cookie.length;
        return unescape(document.cookie.substring(c_start, c_end));
      }
    }
    return '';
  },
};
const RATE_KBPS = 1024;
const RATE_MBPS = 1024 * 1024;
const RATE_GBPS = 1024 * 1024 * 1024;

const LocalUtil = {
  parseQueryString: function (url) {
    url = url == null ? window.location.href : url;

    if (url.indexOf('?') == -1) {
      return {};
    }
    let search = '';
    if (url.indexOf('#') != -1) {
      search = url.substring(url.lastIndexOf('?') + 1, url.indexOf('#'));
      if (window.top?.base?.mpm === 'intl_public') {
        search = url.substring(url.indexOf('?') + 1, url.indexOf('#'));
      }
    } else {
      search = url.substring(url.lastIndexOf('?') + 1);
    }
    const param =
      search && search.indexOf('=') > -1
        ? JSON.parse(
            '{"' +
              decodeURIComponent(search)
                .replace(/"/g, '\\"')
                .replace(/&/g, '","')
                .replace(/=/g, '":"') +
              '"}'
          )
        : {};
    return param;
  },
};

/**
 * 对象辅助工具
 */
const ObjectUtil = {
  /**
   * 深度对象拷贝
   */
  deepCopy(sourceObj) {
    return JSON.parse(JSON.stringify(sourceObj));
  },
  isJSON(str) {
    try {
      if (typeof JSON.parse(str) == 'object') {
        return true;
      }
    } catch (e) {
      return false;
    }
    return false;
  },
  /**
   * 求数组得多数组交集
   * const serveralArr = [
    [1,2,4,5,23,3,2,2,4,3,5,5], 
    [3,2,3,2,2,4,3,1,4,5,6], 
    [3,2,4,3,2,4,1,2,5],
    [3,2,4,5,5,4,3,1,2,2],
    [3,2,23,3,4,1,3,4,5,5,4,3,1,2,2],
    [3,2,4,1,2,5,5,4,3,1,2,2],
    [3,2,4,25,5,4,3,1,2,2],
    ]
    intersectNoRepeatTwice(serveralArr)
   * @param {*} arrs 
   * @returns 
   */
  intersectNoRepeatTwice(arrs) {
    return arrs.reduce(function (prev, cur) {
      // return [...new Set(cur.filter((item)=>prev.includes(item)))]
      return Array.from(new Set(cur.filter((item) => prev.includes(item))));
    });
  },
};

const IPUtil = {
  /**
   * 掩码转反掩码
   *
   * @param subnetMask 子网掩码
   * @return 反掩码
   */
  subnetMask2InverseMask: function (subnetMask) {
    if (!subnetMask) {
      return '';
    }
    let ips = subnetMask.split('.');
    return `${255 - ips[0]}.${255 - ips[1]}.${255 - ips[2]}.${255 - ips[3]}`;
  },
  /**
   **获取IP的网段地址
   * @param {string}ip IP地址如192.168.23.5
   * @param {string} mask 子网掩码地址255.255.255.0
   * @return {string} 网络标识，如192.168.23.0
   */
  getNetCode: function (ip, mask) {
    let ipNum = IPUtil.ipToLong(ip);
    let maskNum = IPUtil.ipToLong(mask);
    let netNum = ipNum & maskNum;
    return IPUtil.longToIP(netNum);
  },
  /**
   *IP地址转换成整型
   *
   * @param {String}
   *str 待验证的用户名字符串.
   * @return {Long} 返回整型
   *
   */
  ipToLong: function (ipstr) {
    let ipArr = new Array();
    ipArr = ipstr.split('.');
    let ip1 = parseInt(ipArr[0], 10) * 256 * 256 * 256;
    let ip2 = parseInt(ipArr[1], 10) * 256 * 256;
    let ip3 = parseInt(ipArr[2], 10) * 256;
    let ip4 = parseInt(ipArr[3], 10);
    let iplong = ip1 + ip2 + ip3 + ip4;
    return iplong;
  },
  /**
   *整型转换成IP地址
   *
   * @param {Long}
   * iplong 待转换的整数.
   * @return {String} 返回IP格式的地址
   *
   */
  longToIP: function (iplong) {
    let ips = new Array(4);
    ips[0] = parseInt((iplong >> 24) & 0xff);
    ips[1] = parseInt((iplong >> 16) & 0xff);
    ips[2] = parseInt((iplong >> 8) & 0xff);
    ips[3] = parseInt(iplong & 0xff);
    return `${ips[0]}.${ips[1]}.${ips[2]}.${ips[3]}`;
  },
  /*
   *得到可变子网掩码的掩码地址@paramvlsm可变子网掩码,例192.168.197.0/27中的27@return掩码地址
   *255.255.255.224
   */
  vlsm2SubnetMask: function (vlsm) {
    //2^32 - 2^(32-vlsm)
    let iplong = (2 << 31) - (2 << (32 - vlsm - 1));
    if (vlsm == 32) {
      iplong -= 1;
    }
    return this.longToIP(iplong);
  },

  mask2len: function (mask) {
    return (
      mask
        .split('.')
        .map(Number)
        .map((part) => (part >>> 0).toString(2))
        .join('')
        .split('1').length - 1
    );
  },

  /**
   *计算子网起始地址(不包括网络地址)
   *
   */
  getLowAddr: function (ip, netMask) {
    let lowAddr = '';
    let ipArray = [];
    let netMaskArray = [];
    // I参数不正确
    if (4 != ip.split('.').length || '' == netMask) {
      return '';
    }
    for (let i = 0; i < 4; i++) {
      ipArray[i] = ip.split('.')[i];
      let num = ipArray[i];
      netMaskArray[i] = netMask.split('.')[i];
      let mask = netMaskArray[i];
      if (num > 255 || num < 0 || (mask > 255 && mask < 0)) {
        return '';
      }
      ipArray[i] = num & mask;
    }
    // 构造最小地址
    for (let i = 0; i < 4; i++) {
      if (i == 3) {
        ipArray[i] = ipArray[i] + 1;
      }
      if ('' == lowAddr) {
        lowAddr += ipArray[i];
      } else {
        lowAddr += '.' + ipArray[i];
      }
    }
    return lowAddr;
  },
  /**
   * 计算子网终止地址（不包括广播地址）
   */
  getHighAddr: function (ip, netMask) {
    let lowAddr = IPUtil.getLowAddr(ip, netMask);
    let hostNumber = IPUtil.getHostNumber(netMask);
    if ('' == lowAddr || hostNumber == 0) {
      return '';
    }
    let lowAddrArray = [];
    for (let i = 0; i < 4; i++) {
      lowAddrArray[i] = lowAddr.split('.')[i];
      if (i == 3) {
        lowAddrArray[i] = Number(lowAddrArray[i] - 1);
      }
    }
    lowAddrArray[3] = lowAddrArray[3] + Number(hostNumber - 1);
    if (lowAddrArray[3] > 255) {
      let k = parseInt(lowAddrArray[3] / 256);
      lowAddrArray[3] = lowAddrArray[3] % 256;
      lowAddrArray[2] = Number(lowAddrArray[2]) + Number(k);
      if (lowAddrArray[2] > 255) {
        k = parseInt(lowAddrArray[2] / 256);
        lowAddrArray[2] = lowAddrArray[2] % 256;
        lowAddrArray[1] = Number(lowAddrArray[1]) + Number(k);
        if (lowAddrArray[1] > 255) {
          k = parseInt(lowAddrArray[1] / 256);
          lowAddrArray[1] = lowAddrArray[1] % 256;
          lowAddrArray[0] = Number(lowAddrArray[0]) + Number(k);
        }
      }
    }
    let highAddr = '';
    for (let i = 0; i < 4; i++) {
      if (i == 3) {
        lowAddrArray[i] = lowAddrArray[i] - 1;
      }
      if ('' == highAddr) {
        highAddr = lowAddrArray[i];
      } else {
        highAddr += '.' + lowAddrArray[i];
      }
    }
    return highAddr;
  },
  /**
   * 获取主机数
   *
   * @param netMask
   * @returns {Number}
   */
  getHostNumber: function (netMask) {
    let hostNumber = 0;
    let netMaskArray = [];
    for (let i = 0; i < 4; i++) {
      netMaskArray[i] = netMask.split('.')[i];
      if (netMaskArray[i] < 255) {
        hostNumber = Math.pow(256, 3 - i) * (256 - netMaskArray[i]);
        break;
      }
    }
    return hostNumber;
  },
  /**
   * D类地址
   * @param {String} ipAddr
   * @returns
   */
  isMulticastAddress(ipAddr) {
    let startip = this.ipToLong('224.0.0.0');
    let endip = this.ipToLong('239.255.255.255');
    let toip = this.ipToLong(ipAddr);
    if (toip >= startip && toip <= endip) {
      return true;
    } else {
      return false;
    }
  },
  /**
   * E类地址
   * @param {string} ipAddr
   * @returns
   */
  isEtypeAddress(ipAddr) {
    let startip = this.ipToLong('240.0.0.0');
    let endip = this.ipToLong('255.255.255.255');
    let toip = this.ipToLong(ipAddr);
    if (toip >= startip && toip <= endip) {
      return true;
    } else {
      return false;
    }
  },
  /**
   *是否网络地址
   * @param {string} ip
   * @param {string} netmask
   * @returns
   */
  checkIsNetAddress(ip, netmask) {
    let result = this.ipToLong(ip) & ~this.ipToLong(netmask);
    return result == 0 ? true : false;
  },
  /**
   *判断是否广播地址
   *
   * @param {string} ip
   * @param {string} netmask
   * @returns
   */
  checkIsBroadcastAddress(ip, netmask) {
    let result = (this.ipToLong(ip) + 1) & ~this.ipToLong(netmask);
    return result == 0 ? true : false;
  },
  /**
   * 判断两个IP是否是在同一网段
   * @param {*} addr1
   * @param {*} addr2
   * @param {*} mask
   */
  isEqualIPAddress: function (addr1, addr2, mask) {
    if (!addr1 || !addr2 || !mask) {
      return false;
    }
    let res1 = [],
      res2 = [];
    addr1 = addr1.split('.');
    addr2 = addr2.split('.');
    mask = mask.split('.');
    for (let i = 0, ilen = addr1.length; i < ilen; i += 1) {
      res1.push(parseInt(addr1[i]) & parseInt(mask[i]));
      res2.push(parseInt(addr2[i]) & parseInt(mask[i]));
    }
    if (res1.join('.') == res2.join('.')) {
      return true;
    } else {
      return false;
    }
  },
  /**
   * 格式化速率
   * @param {*} value
   * 单位是KB/s
   */
  formatRate: function (value) {
    let data;

    if (value != undefined && value != null) {
      if (value * 8 > 1024 * 1024) {
        data = ((value * 8) / 1024 / 1024).toFixed(2) + 'Gbps';
      } else if (value * 8 > 1024) {
        data = ((value * 8) / 1024).toFixed(2) + 'Mbps';
      } else {
        data = parseFloat(value * 8).toFixed(2) + 'Kbps';
      }
    } else {
      data = i18nRender('intelligentterminal.unkown');
    }

    return data;
  },
  /**
   * 格式化速率
   * @param {*} value
   * value的单位是bps
   */
  formatBpsRate: function (value) {
    let data;
    if (value != undefined && value != null) {
      if (value > RATE_GBPS) {
        data = (value / RATE_GBPS).toFixed(2) + 'Gbps';
      } else if (value > RATE_MBPS) {
        data = (value / RATE_MBPS).toFixed(2) + 'Mbps';
      } else {
        data = (value / RATE_KBPS).toFixed(2) + 'Kbps';
      }
    } else {
      data = i18nRender('intelligentterminal.unkown');
    }

    return data;
  },

  /**
   * 格式化速率
   * @param {*} value
   * 单位是KB/s
   */
  formatBRate: function (value) {
    let data;
    if (value != undefined && value != null) {
      if (value * 8 > RATE_GBPS) {
        data = ((value * 8) / RATE_GBPS).toFixed(2) + 'Gbps';
      } else if (value * 8 > RATE_MBPS) {
        data = ((value * 8) / RATE_MBPS).toFixed(2) + 'Mbps';
      } else if (value * 8 > RATE_KBPS) {
        data = ((value * 8) / RATE_KBPS).toFixed(2) + 'Kbps';
      } else {
        data = parseFloat(value * 8).toFixed(2) + 'bps';
      }
    } else {
      data = i18nRender('intelligentterminal.unkown');
    }

    return data;
  },

  /**
   * 格式化流量
   * @param {*} value
   * value的单位B
   */
  formatFlow: function (value) {
    let data;
    if (value != undefined && value != null) {
      if (value > 1024 * 1024 * 1024) {
        data = (value / 1024 / 1024 / 1024).toFixed(2) + 'GB';
      } else if (value > 1024 * 1024) {
        data = (value / 1024 / 1024).toFixed(2) + 'MB';
      } else if (value > 1024) {
        data = (value / 1024).toFixed(2) + 'KB';
      } else {
        data = parseFloat(value).toFixed(2) + 'B';
      }
    } else {
      data = i18nRender('intelligentterminal.unkown');
    }

    return data;
  },
};

const ValidateIPRange = function (subnet, netmask) {
  /**
   * subnetBin: 子网的二进制表示
   * netmaskBin: 子网掩码的二进制表示
   * networkLength: 子网的网络地址长度
   * subnetNetBit: 子网的网络地址位二进制表示
   * subnetHostBit: 子网的主机地址二进制表示
   * broadcastHostBit: 广播地址二进制表示
   */
  let subnetBin = _ipToBin(subnet);
  let netmaskBin = _ipToBin(netmask);
  let networkLength = _getNetworkLength();
  let subnetNetBit = '';
  let subnetHostBit = '';
  let broadcastHostBit = '';

  //判断目标IP是不是属于指定的子网内
  function isInRange(targetIP) {
    getNetwork();
    let targetIPNetworkBin = _ipToBin(targetIP);
    let targetIPNetBit = targetIPNetworkBin.substr(0, networkLength);
    let targetIPHostBit = targetIPNetworkBin.substr(networkLength);
    //排除网络地址与广播地址
    if (
      targetIPNetBit == subnetNetBit &&
      targetIPHostBit != subnetHostBit &&
      targetIPHostBit != broadcastHostBit
    ) {
      return true;
    } else {
      return false;
    }
  }

  function getNetwork() {
    let networkBin = _andOpration(subnetBin, netmaskBin);
    subnetNetBit = networkBin.substr(0, networkLength);
    subnetHostBit = networkBin.substr(networkLength);
    broadcastHostBit = subnetHostBit.replace(/0/g, '1');
    return _binToIp(networkBin);
  }

  function getBroadcast() {
    getNetwork();
    let broadcastBin = subnetNetBit + broadcastHostBit;
    return _binToIp(broadcastBin);
  }

  function getNetworkLength() {
    return networkLength;
  }

  //获取网络地址长度
  function _getNetworkLength() {
    let length = 0;
    for (let i = 0; i < 32; i++) {
      if (netmaskBin.charAt(i) == '1') {
        length++;
      } else {
        break;
      }
    }
    return length;
  }

  function _andOpration(ipBin, netmaskBin) {
    let result = '';
    for (let i = 0; i < 32; i++) {
      result += parseInt(ipBin.charAt(i)) & parseInt(netmaskBin.charAt(i));
    }
    return result;
  }

  function _ipToBin(ip) {
    let subIpArray = ip.split('.');
    let ipBin = '';
    for (let i = 0; i < subIpArray.length; i++) {
      ipBin += _binCompletion(parseInt(subIpArray[i]).toString(2));
    }
    return ipBin;
  }

  function _binToIp(bin) {
    let ip = '';
    for (let i = 0; i < bin.length; i += 8) {
      ip += '.' + parseInt(bin.substr(i, 8), 2);
    }
    ip = ip.substr(1);
    return ip;
  }

  function _binCompletion(subBin) {
    let complBin = subBin;
    if (subBin.length < 8) {
      let length = subBin.length;
      for (let i = 0; i < 8 - length; i++) {
        complBin = '0' + complBin;
      }
    }
    return complBin;
  }

  return {
    isInRange,
    getNetwork,
    getNetworkLength,
    getBroadcast,
  };
};

const TimeZoneUtil = {
  getGroupTimestamp: function (timestamp, timezone) {
    // 获得浏览器所在当地时间的偏移值（毫秒）
    let browserOffset = TimeZoneUtil.getLocalOffset();

    // 获得当前分组的时区偏移值（毫秒）
    let groupOffset = TimeZoneUtil.getCurrentGroupOffset(timezone);

    // 分组时间
    timestamp = timestamp - browserOffset + groupOffset;
    return timestamp;
  },

  getCurrentGroupOffset: function (timezone) {
    if (timezone) {
      // 获得指定时区时间的偏移值（毫秒）
      return TimeZoneUtil.getTimezoneOffset(timezone);
    } else {
      return 0;
    }
  },

  /**
   * 获得指定时区时间的偏移值（毫秒）
   */
  getTimezoneOffset: function (timezone) {
    // 根据时区获得时区字符串
    let timezoneStr = '';

    if (timezone.includes('Etc/GMT-')) {
      timezone = timezone.replace('Etc/GMT-', 'GMT+') + ':00';
    } else if (timezone.includes('Etc/GMT+')) {
      timezone = timezone.replace('Etc/GMT+', 'GMT-') + ':00';
    }

    if (/GMT/.test(timezone)) {
      timezoneStr = `(${timezone})`;
    } else {
      for (let i in TimeZone) {
        if (TimeZone[i].key == timezone) {
          timezoneStr = TimeZone[i].value;
          break;
        }
      }
    }

    // 正则表达式
    let reExp1 = /\(GMT\+[\d]{1,2}:[\d]{2}\)/; // 匹配东时区
    let reExp2 = /\(GMT\-[\d]{1,2}:[\d]{2}\)/; // 匹配西时区
    let reExp = /[\d]{1,2}/g; // 匹配小时、分钟
    let num = 0; // 东时区时为1，中时区为0，西时区时为-1

    // 判断是否为东时区
    if (reExp1.test(timezoneStr)) {
      num = 1;
    }
    // 判断是否为西时区
    else if (reExp2.test(timezoneStr)) {
      num = -1;
    }
    // 非法时区
    else {
      console.error('The timezone is not right!');
      return 0;
    }

    // 匹配时区中的小时、分钟
    let times = timezoneStr.match(reExp);
    let hour = parseInt(times[0]);
    let minute = parseInt(times[1]);

    if (TimeZoneUtil.isSummerTime()) {
      hour = hour + 1;
    }

    // 转换成指定时区的时间
    return num * (hour * 3600000 + minute * 60000);
  },

  isSummerTime: function () {
    let year = new Date().getYear();
    if (year < 1000) {
      year += 1900;
    }

    let firstSwitch = 0;
    let secondSwitch = 0;
    let lastOffset = 99;

    // Loop through every month of the current year
    for (let i = 0; i < 12; i++) {
      // Fetch the timezone value for the month
      let newDate = new Date(Date.UTC(year, i, 0, 0, 0, 0, 0));
      let tz = (-1 * newDate.getTimezoneOffset()) / 60;

      // Capture when a timzezone change occurs
      if (tz > lastOffset) {
        firstSwitch = i - 1;
      } else if (tz < lastOffset) {
        secondSwitch = i - 1;
      }

      lastOffset = tz;
    }

    // Go figure out date/time occurences a minute before
    // a DST adjustment occurs
    let secondDstDate = TimeZoneUtil.findDstSwitchDate(year, secondSwitch);
    let firstDstDate = TimeZoneUtil.findDstSwitchDate(year, firstSwitch);

    if (firstDstDate == null && secondDstDate == null) {
      return false;
    } else {
      let nowTimestamp = new Date().getTime();
      if (nowTimestamp >= firstDstDate && nowTimestamp <= secondDstDate) {
        return true;
      } else {
        return false;
      }
    }
  },

  findDstSwitchDate: function (year, month) {
    // Set the starting date
    let baseDate = new Date(Date.UTC(year, month, 0, 0, 0, 0, 0));
    let changeMinute = -1;
    let baseOffset = (-1 * baseDate.getTimezoneOffset()) / 60;

    // Loop to find the exact day a timezone adjust occurs
    for (let day = 0; day < 50; day++) {
      let tmpDate = new Date(Date.UTC(year, month, day, 0, 0, 0, 0));
      let tmpOffset = (-1 * tmpDate.getTimezoneOffset()) / 60;

      // Check if the timezone changed from one day to the next
      if (tmpOffset != baseOffset) {
        let minutes = 0;

        // Back-up one day and grap the offset
        tmpDate = new Date(Date.UTC(year, month, day - 1, 0, 0, 0, 0));
        tmpOffset = (-1 * tmpDate.getTimezoneOffset()) / 60;

        // Count the minutes until a timezone chnage occurs
        while (changeMinute == -1) {
          tmpDate = new Date(Date.UTC(year, month, day - 1, 0, minutes, 0, 0));
          tmpOffset = (-1 * tmpDate.getTimezoneOffset()) / 60;

          // Determine the exact minute a timezone change
          // occurs
          if (tmpOffset != baseOffset) {
            // Back-up a minute to get the date/time just
            // before a timezone change occurs
            tmpOffset = new Date(
              Date.UTC(year, month, day - 1, 0, minutes - 1, 0, 0)
            );
            changeMinute = minutes;
            break;
          } else {
            minutes++;
          }
        }

        // Capture the time stamp
        tmpDate = new Date(
          Date.UTC(year, month, day - 1, 0, minutes - 1, 0, 0)
        ).getTime();
        return tmpDate;
      }
    }
  },
  /**
   * 获得浏览器所在当地时间的偏移值（毫秒）
   */
  getLocalOffset: function () {
    // 注意，getTimezoneOffset()方法的负返回值表示当地时间在全球标准时间（UTC）之前，而正返回值则表示当地时间在全球标准时间（UTC）之后。
    return -new Date().getTimezoneOffset() * 60000;
  },
};
const RadioUtil = {
  /**
   * 获取射频序列号
   * @param {*} radioIndex
   * @returns
   */
  getbandIdx: function (radioIndex) {
    const indexStr = radioIndex + '';
    if (indexStr.indexOf('.') > 0) {
      const arr = indexStr.split('.');
      const radioIdx = parseInt(arr[0]);
      const bandIdx = parseInt(arr[1]);
      const n = bandIdx > 5 ? radioIdx - 2 : radioIdx - 1;
      if (n > 1) {
        return n;
      }
    }
    return '';
  },
  /**
   * 获取射频下标
   * @param {*} radioIndex
   * @returns
   */
  getRadioSubscript: function (radioIndex) {
    const bandIdx = this.getbandIdx(radioIndex);
    if (bandIdx) {
      return `${i18nRender('wirelessConfig.RadioSubscript', { num: bandIdx })}`;
    }
    return '';
  },
  /**
   * 根据radioIndex获取band
   * @param {*} radioIndex
   * @returns
   */
  getRadioBand(radioIndex) {
    let band = '';
    if (radioIndex.indexOf('.') > 0) {
      const bandIdx = radioIndex.split('.')[1];
      switch (bandIdx) {
        case '4': {
          band = '2.4G';
          break;
        }
        default: {
          band = `${bandIdx}G`;
          break;
        }
      }
    } else {
      switch (radioIndex) {
        case '1': {
          band = '2.4G';
          break;
        }
        case '2': {
          band = '5G';
          break;
        }
      }
    }
    return band;
  },
};

export {
  ObjectUtil,
  IPUtil,
  TimeZoneUtil,
  ValidateIPRange,
  SysConf,
  LocalUtil,
  RadioUtil,
};
